using System;
using System.Collections.Generic;
using System.Net;
using System.Windows.Forms;
using Devv.Core.Utils;
using TweetSharp;

namespace Devv.Threeter.Twitter
{
	public class TwitterManager
	{
		#region Consts

		public const String BASEACCOUNTURL = "http://twitter.com/#!/";
		public const Int32 MAXCHARACTERS = 140;


		#endregion

		#region Properties

		// Please change here to use your own key and secret from Twitter!!!
		public readonly static TwitterService Service = new TwitterService(ConfigUtil.GetConfig("Twitter.ConsumerKey"), ConfigUtil.GetConfig("Twitter.ConsumerSecret"));

		private static Account CurrentAccount;
		public static Account LoggedAccount
		{
			get
			{
				return CurrentAccount;
			}
			set
			{
				if (value != null && CurrentAccount != null && CurrentAccount.Username == value.Username && CurrentAccount.Secret == value.Secret)
				{
					return;
				}

				CurrentAccount = value;

				if (value != null && !String.IsNullOrEmpty(value.Token))
				{
					Service.AuthenticateWith(value.Token, value.Secret);
				}
			}
		}

		#endregion

		#region Private constructor and init

		private TwitterManager()
		{
		}

		public static void Load()
		{
			Service.Format = TwitterServiceFormat.Json;
			Service.IncludeEntities = true;
			Service.UserAgent = ConfigUtil.GetConfig("Devv.AppName");

			LoggedAccount = new Account();
		}

		#endregion

		#region Update

		public static void UpdateStatus(String message)
		{
			if (!AuthIsOk())
			{
				ShowFormAccounts();
			}

			TwitterStatus status = Service.SendTweet(message);

			if (status.Id < 1)
			{
				String error = status.RawSource;

				if (error.Contains("\""))
				{
					error = error.Substring(error.IndexOf("error\":"));
					error = error.Substring(0, error.IndexOf("\"") - 1);
				}

				throw new ApplicationException(error);
			}
		}

		#endregion

		#region Get timeline

		public static IEnumerable<TwitterStatus> GetTimeline()
		{
			if (!AuthIsOk())
			{
				ShowFormAccounts();
			}

			try
			{
				return Service.ListTweetsOnHomeTimeline();
			}
			catch (Exception ex)
			{
				if (!IsError401(ex))
				{
					throw;
				}

				ShowFormAccounts();
			}

			return null;
		}

		public static IEnumerable<TwitterStatus> GetTimeline(Int64 sinceId)
		{
			if (!AuthIsOk())
			{
				ShowFormAccounts();
			}

			try
			{
				return Service.ListTweetsOnHomeTimelineSince(sinceId);
			}
			catch (Exception ex)
			{
				if (!IsError401(ex))
				{
					throw;
				}

				ShowFormAccounts();
			}

			return null;
		}

		public static IEnumerable<TwitterStatus> GetTimeline(String username, Int64 sinceId)
		{
			if (!AuthIsOk())
			{
				ShowFormAccounts();
			}

			try
			{
				return Service.ListTweetsOnListSince(username, username, sinceId);
			}
			catch (Exception ex)
			{
				if (!IsError401(ex))
				{
					throw;
				}

				ShowFormAccounts();
			}

			return null;
		}

		#endregion

		#region Get friends

		public static TwitterCursorList<TwitterUser> GetFriends()
		{
			if (!AuthIsOk())
			{
				ShowFormAccounts();
			}

			try
			{
				return Service.ListFollowers();
			}
			catch (Exception ex)
			{
				if (!IsError401(ex))
				{
					throw;
				}

				ShowFormAccounts();
			}

			return null;
		}

		#endregion

		#region Error checking

		private static Boolean AuthIsOk()
		{
			if (Service.Response != null)
			{
				return (Service.Response.StatusCode != HttpStatusCode.Unauthorized && Service.Response.StatusCode != HttpStatusCode.Forbidden);
			}

			return true;
		}

		private static Boolean IsError401(Exception ex)
		{
			if (ex.Message.Contains("401"))
			{
				return true;
			}

			return false;
		}

		private static void ShowFormAccounts()
		{
			MessageBox.Show(Messages.ErrorInvalidLogin, Messages.Login, MessageBoxButtons.OK, MessageBoxIcon.Warning);
		}

		#endregion

		#region Helper methods

		internal static String GetCurrentAccountUrl()
		{
			return BASEACCOUNTURL + LoggedAccount.Username;
		}

		#endregion
	}
}